/***************************************************************************
 *
 *   Copyright (C) 2004 by Willem van Straten
 *   Licensed under the Academic Free License version 2.1
 *
 ***************************************************************************/
#include "ColourMap.h"
#include <cpgplot.h>

//! Default constructor
pgplot::ColourMap::ColourMap ()
{
  name = GreyScale;
  contrast = 1.0;
  brightness = 0.5;
  logarithmic = false;
}

pgplot::ColourMap::ColourMap (const Name _name) :
  name(_name),
  contrast(1.0),
  brightness(0.5),
  logarithmic(false)
{}


//! Set the contrast (0 to 1; normally 1)
void pgplot::ColourMap::set_contrast (float _contrast)
{
  contrast = _contrast;
}


//! Set the brightness (0 to 1; normally 5)
void pgplot::ColourMap::set_brightness (float _brightness)
{
  brightness = _brightness;
}


//! Set the colour map name
void pgplot::ColourMap::set_name (Name _name)
{
  name = _name;
}

void pgplot::ColourMap::apply ()
{
  int itf = 0;
  if (logarithmic)
    itf = 1;

  cpgsitf (itf);

  switch (name) {
    
  case GreyScale: {
    
    float grey_l[] = { 0.0, 1.};
    float grey_r[] = { 0.0, 1.};
    float grey_g[] = { 0.0, 1.};
    float grey_b[] = { 0.0, 1.};
    
    cpgctab (grey_l, grey_r, grey_g, grey_b, 2, contrast, brightness);
    
    break;
  }
  
  case Inverse: {
    
    float grey_l[] = { 0.0, 1.0};
    float grey_r[] = { 1.0, 0.0};
    float grey_g[] = { 1.0, 0.0};
    float grey_b[] = { 1.0, 0.0};
    
    cpgctab (grey_l, grey_r, grey_g, grey_b, 2, contrast, brightness);
    
    break;
  }

  case Heat: {
    
    float heat_l[] = {0.0, 0.2, 0.4, 0.6, 1.0};
    float heat_r[] = {0.0, 0.5, 1.0, 1.0, 1.0};
    float heat_g[] = {0.0, 0.0, 0.5, 1.0, 1.0};
    float heat_b[] = {0.0, 0.0, 0.0, 0.3, 1.0};
    
    cpgctab (heat_l, heat_r, heat_g, heat_b, 5, contrast, brightness);
    
    break;
  }
  
  case Cold: {
    
    float cool_l[] = {0.0, 0.2, 0.4, 0.6, 1.0};
    float cool_r[] = {0.0, 0.0, 0.0, 0.3, 1.0};
    float cool_g[] = {0.0, 0.0, 0.5, 1.0, 1.0};
    float cool_b[] = {0.0, 0.5, 1.0, 1.0, 1.0};
    
    cpgctab (cool_l, cool_r, cool_g, cool_b, 5, contrast, brightness);
    
    break;
  }
  
  case Plasma: {
    
    float cool_l[] = {0.0, 0.2, 0.4, 0.6, 1.0};
    float cool_r[] = {0.0, 0.0, 0.5, 1.0, 1.0};
    float cool_g[] = {0.0, 0.0, 0.0, 0.3, 1.0};
    float cool_b[] = {0.0, 0.5, 1.0, 1.0, 1.0};
    
    cpgctab (cool_l, cool_r, cool_g, cool_b, 5, contrast, brightness);
    
    break;
  }
  
  case Forest: {
    
    float cool_l[] = {0.0, 0.4, 0.7, 0.9, 1.0};
    float cool_r[] = {0.0, 0.0, 0.0, 0.3, 1.0};
    float cool_g[] = {0.0, 0.5, 1.0, 1.0, 1.0};
    float cool_b[] = {0.0, 0.0, 0.5, 1.0, 1.0};

    cpgctab (cool_l, cool_r, cool_g, cool_b, 5, contrast, brightness);
    
    break;
  }
  
  case AlienGlow: {
    
    float test_l[] = { 0.0, 0.1, 0.1, 0.2, 0.2, 0.3, 0.3, 0.4, 0.4, 0.5,
		       0.5, 0.6, 0.6, 0.7, 0.7, 0.8, 0.8, 0.9, 0.9, 1.};
    float test_r[] = { 0.0, 0.0, 0.3, 0.3, 0.5, 0.5, 0.0, 0.0, 0.0, 0.0,
		       0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.};
    float test_g[] = { 0.0, 0.0, 0.3, 0.3, 0.0, 0.0, 0.0, 0.0, 0.8, 0.8,
		       0.6, 0.6, 1.0, 1.0, 1.0, 1.0, 0.8, 0.8, 0.0, 0.};
    float test_b[] = { 0.0, 0.0, 0.3, 0.3, 0.7, 0.7, 0.7, 0.7, 0.9, 0.9,
		       0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.};
    
    cpgctab (test_l, test_r, test_g, test_b, 20, contrast, brightness);
    
    break;
  }

  case CubeHelix: {
    float test_l[] = { 0.0,.00390625,.0078125,.01171875,.015625,.01953125,.0234375,.02734375,.03125,
                       .03515625,.0390625,.04296875,.046875,.05078125,.0546875,.05859375,.0625,
		       .06640625,.0703125,.07421875,.078125,.08203125,.0859375,.08984375,.09375,
		       .09765625,.1015625,.10546875,.109375,.11328125,.1171875,.12109375,.125,
		       .12890625,.1328125,.13671875,.140625,.14453125,.1484375,.15234375,.15625,
		       .16015625,.1640625,.16796875,.171875,.17578125,.1796875,.18359375,.1875,
		       .19140625,.1953125,.19921875,.203125,.20703125,.2109375,.21484375,.21875,
		       .22265625,.2265625,.23046875,.234375,.23828125,.2421875,.24609375,.25,
		       .25390625,.2578125,.26171875,.265625,.26953125,.2734375,.27734375,.28125,
		       .28515625,.2890625,.29296875,.296875,.30078125,.3046875,.30859375,.3125,
		       .31640625,.3203125,.32421875,.328125,.33203125,.3359375,.33984375,.34375,
		       .34765625,.3515625,.35546875,.359375,.36328125,.3671875,.37109375,.375,
		       .37890625,.3828125,.38671875,.390625,.39453125,.3984375,.40234375,.40625,
		       .41015625,.4140625,.41796875,.421875,.42578125,.4296875,.43359375,.4375,
		       .44140625,.4453125,.44921875,.453125,.45703125,.4609375,.46484375,.46875,
		       .47265625,.4765625,.48046875,.484375,.48828125,.4921875,.49609375,.5,
		       .50390625,.5078125,.51171875,.515625,.51953125,.5234375,.52734375,.53125,
		       .53515625,.5390625,.54296875,.546875,.55078125,.5546875,.55859375,.5625,
		       .56640625,.5703125,.57421875,.578125,.58203125,.5859375,.58984375,.59375,
		       .59765625,.6015625,.60546875,.609375,.61328125,.6171875,.62109375,.625,
		       .62890625,.6328125,.63671875,.640625,.64453125,.6484375,.65234375,.65625,
		       .66015625,.6640625,.66796875,.671875,.67578125,.6796875,.68359375,.6875,
		       .69140625,.6953125,.69921875,.703125,.70703125,.7109375,.71484375,.71875,
		       .72265625,.7265625,.73046875,.734375,.73828125,.7421875,.74609375,.75,
		       .75390625,.7578125,.76171875,.765625,.76953125,.7734375,.77734375,.78125,
		       .78515625,.7890625,.79296875,.796875,.80078125,.8046875,.80859375,.8125,
		       .81640625,.8203125,.82421875,.828125,.83203125,.8359375,.83984375,.84375,
		       .84765625,.8515625,.85546875,.859375,.86328125,.8671875,.87109375,.875,
		       .87890625,.8828125,.88671875,.890625,.89453125,.8984375,.90234375,.90625,
		       .91015625,.9140625,.91796875,.921875,.92578125,.9296875,.93359375,.9375,
		       .94140625,.9453125,.94921875,.953125,.95703125,.9609375,.96484375,.96875,
		       .97265625,.9765625,.98046875,.984375,.98828125,.9921875,.99609375,1.  };
    float test_r[] = {  0.00,0.0421039,0.0656598,0.0845639,0.100688,0.114818,0.127383,0.138649,
			0.148799,0.157962,0.166241,0.173713,0.180444,0.186488,0.191891,0.196694,
		       	0.200934,0.204644,0.207854,0.210594,0.21289,0.214768,0.216252,0.217366,
			0.218133,0.218575,0.218715,0.218574,0.218172,0.217532,0.216674,0.215617,
			0.214382,0.21299,0.211459,0.209808,0.208058,0.206227,0.204334,0.202396,
			0.200434,0.198463,0.196501,0.194567,0.192676,0.190846,0.189091,0.187429,
			0.185874,0.184441,0.183145,0.181999,0.181017,0.180212,0.179596,0.179182,
			0.17898,0.179001,0.179256,0.179753,0.180503,0.181513,0.182791,0.184345,
			0.18618,0.188303,0.190719,0.193433,0.196447,0.199766,0.203392,0.207328,
			0.211573,0.21613,0.220997,0.226175,0.231662,0.237455,0.243553,0.249953,
			0.256649,0.263639,0.270918,0.278478,0.286316,0.294423,0.302794,0.311419,
			0.320292,0.329404,0.338745,0.348306,0.358077,0.368049,0.37821,0.388549,
			0.399055,0.409718,0.420524,0.431461,0.442518,0.453682,0.46494,0.476279,
			0.487687,0.49915,0.510655,0.52219,0.533739,0.545292,0.556834,0.568352,
			0.579833,0.591265,0.602634,0.613928,0.625134,0.63624,0.647233,0.658103,
			0.668837,0.679424,0.689854,0.700114,0.710196,0.720088,0.729782,0.739269,
			0.748538,0.757583,0.766394,0.774965,0.783288,0.791357,0.799166,0.806709,
			0.813981,0.820977,0.827693,0.834126,0.840273,0.846131,0.851697,0.856972,
			0.861953,0.86664,0.871033,0.875134,0.878942,0.88246,0.885691,0.888635,
			0.891297,0.893681,0.89579,0.89763,0.899204,0.900519,0.90158,0.902394,
			0.902968,0.903309,0.903423,0.90332,0.903006,0.902491,0.901784,0.900893,
			0.899827,0.898597,0.897213,0.895683,0.894018,0.892229,0.890327,0.88832,
			0.886221,0.88404,0.881788,0.879476,0.877114,0.874714,0.872285,0.869839,
			0.867387,0.864939,0.862505,0.860095,0.857721,0.855391,0.853115,0.850904,
			0.848765,0.846709,0.844743,0.842877,0.841118,0.839475,0.837954,0.836563,
			0.835308,0.834197,0.833234,0.832425,0.831777,0.831292,0.830976,0.830833,
			0.830865,0.831077,0.83147,0.832046,0.832807,0.833755,0.834889,0.836211,
			0.83772,0.839414,0.841294,0.843357,0.845602,0.848025,0.850624,0.853396,
			0.856337,0.859442,0.862707,0.866127,0.869697,0.873411,0.877263,0.881246,
			0.885354,0.889579,0.893915,0.898354,0.902888,0.907508,0.912207,0.916977,
			0.921807,0.926691,0.931617,0.936579,0.941565,0.946568,0.951578,0.956585,
			0.961579,0.966553,0.971496,0.976399,0.981254,0.98605,0.990778,0.995432,1.0};
    float test_g[] = {  0.00,0.0136397,0.0220915,0.029493,0.0363794,0.0429735,0.0493956,0.0557204,
     			0.0619987,0.0682667,0.0745516,0.080874,0.0872503,0.093693,0.100212,0.106816,
			0.113511,0.120301,0.12719,0.13418,0.141273,0.148469,0.155768,0.163168,
			0.170669,0.178268,0.185963,0.193749,0.201624,0.209584,0.217623,0.225737,
			0.233921,0.242169,0.250476,0.258835,0.26724,0.275684,0.284162,0.292666,
			0.301188,0.309723,0.318263,0.326799,0.335326,0.343836,0.35232,0.360772,
			0.369184,0.377549,0.385859,0.394107,0.402286,0.410388,0.418407,0.426335,
			0.434166,0.441893,0.449509,0.457009,0.464386,0.471634,0.478747,0.48572,
			0.492548,0.499226,0.505748,0.512112,0.518311,0.524343,0.530203,0.535889,
			0.541397,0.546725,0.55187,0.55683,0.561603,0.566188,0.570584,0.574789,
			0.578804,0.582628,0.586261,0.589703,0.592957,0.596021,0.598899,0.601591,
			0.6041,0.606428,0.608578,0.610552,0.612354,0.613987,0.615455,0.616762,
			0.617913,0.618911,0.619762,0.62047,0.621041,0.62148,0.621792,0.621985,
			0.622062,0.622031,0.621898,0.621669,0.62135,0.620949,0.620472,0.619926,
			0.619318,0.618654,0.617942,0.617189,0.616402,0.615588,0.614753,0.613906,
			0.613053,0.6122,0.611356,0.610527,0.609719,0.608939,0.608195,0.607491,
			0.606836,0.606234,0.605692,0.605217,0.604812,0.604485,0.604241,0.604084,
			0.604019,0.604052,0.604187,0.604428,0.60478,0.605245,0.605828,0.606532,
			0.60736,0.608315,0.6094,0.610615,0.611965,0.61345,0.615072,0.616831,
			0.61873,0.620768,0.622945,0.625263,0.627721,0.630317,0.633052,0.635925,
			0.638933,0.642076,0.645352,0.648759,0.652294,0.655956,0.65974,0.663645,
			0.667667,0.671802,0.676048,0.680399,0.684853,0.689405,0.694051,0.698787,
			0.703607,0.708506,0.713481,0.718526,0.723636,0.728806,0.73403,0.739303,
			0.74462,0.749976,0.755364,0.760779,0.766216,0.771669,0.777133,0.782603,
			0.788071,0.793534,0.798987,0.804422,0.809836,0.815224,0.820579,0.825898,
			0.831176,0.836407,0.841587,0.846713,0.851779,0.856782,0.861717,0.866581,
			0.871371,0.876083,0.880713,0.88526,0.88972,0.894091,0.89837,0.902556,
			0.906647,0.910641,0.914536,0.918332,0.922028,0.925623,0.929117,0.93251,
			0.935801,0.938992,0.942083,0.945074,0.947966,0.950762,0.953462,0.956069,
			0.958584,0.96101,0.963349,0.965603,0.967776,0.969871,0.97189,0.973838,
			0.975718,0.977533,0.979288,0.980986,0.982632,0.984231,0.985786,0.987302,
			0.988785,0.990237,0.991666,0.993075,0.994469,0.995853,0.997233,0.998614,1.0};
    float test_b[] = {  0.00,0.0374963,0.0603695,0.0802059,0.0984532,0.115682,0.132181,0.148114,
      			0.163581,0.178646,0.193349,0.207718,0.221768,0.235508,0.248943,0.262073,
			0.274897,0.28741,0.299607,0.311482,0.323028,0.334238,0.345105,0.355622,
			0.36578,0.375574,0.384995,0.394038,0.402697,0.410965,0.418838,0.426312,
			0.433382,0.440046,0.4463,0.452143,0.457573,0.46259,0.467193,0.471384,
			0.475164,0.478535,0.481501,0.484064,0.486229,0.488,0.489385,0.490388,
			0.491016,0.491278,0.491182,0.490736,0.489949,0.488833,0.487396,0.485651,
			0.483609,0.481282,0.478682,0.475823,0.472718,0.46938,0.465824,0.462064,
			0.458114,0.453991,0.449709,0.445283,0.44073,0.436064,0.431303,0.426462,
			0.421557,0.416604,0.41162,0.40662,0.401621,0.396638,0.391689,0.386787,
			0.381949,0.377191,0.372527,0.367972,0.363541,0.359248,0.355108,0.351133,
			0.347337,0.343734,0.340334,0.337151,0.334196,0.33148,0.329014,0.326807,
			0.324869,0.323209,0.321836,0.320757,0.319979,0.31951,0.319355,0.31952,
			0.320009,0.320826,0.321976,0.323461,0.325284,0.327445,0.329947,0.332789,
			0.335971,0.339493,0.343352,0.347547,0.352076,0.356933,0.362117,0.367621,
			0.373442,0.379573,0.386009,0.392742,0.399765,0.407071,0.414651,0.422497,
			0.430599,0.438949,0.447535,0.456349,0.465378,0.474612,0.48404,0.49365,
			0.50343,0.513368,0.523451,0.533667,0.544004,0.554447,0.564985,0.575604,
			0.58629,0.597032,0.607814,0.618625,0.62945,0.640278,0.651094,0.661885,
			0.672639,0.683344,0.693985,0.704552,0.715032,0.725414,0.735685,0.745834,
			0.755851,0.765725,0.775445,0.785001,0.794385,0.803586,0.812596,0.821407,
			0.830011,0.838401,0.846569,0.854509,0.862215,0.869682,0.876904,0.883878,
			0.890599,0.897064,0.90327,0.909215,0.914897,0.920315,0.925467,0.930355,
			0.934977,0.939336,0.943432,0.947268,0.950845,0.954167,0.957238,0.96006,
			0.962639,0.964979,0.967086,0.968965,0.970623,0.972066,0.973301,0.974335,
			0.975177,0.975833,0.976314,0.976626,0.976779,0.976783,0.976647,0.97638,
			0.975992,0.975494,0.974895,0.974206,0.973437,0.9726,0.971703,0.970759,
			0.969777,0.968769,0.967744,0.966714,0.965689,0.964679,0.963694,0.962745,
			0.961841,0.960992,0.960208,0.959498,0.95887,0.958334,0.957899,0.957571,
			0.957359,0.95727,0.957312,0.957491,0.957813,0.958285,0.958911,0.959696,
			0.960646,0.961764,0.963054,0.964519,0.966162,0.967984,0.969988,0.972175,
			0.974544,0.977097,0.979833,0.982751,0.985849,0.989126,0.992578,0.996204,1.0};

    cpgctab ( test_l, test_r, test_g, test_b, 257, contrast, brightness);
    break;
  }
  
  case Test: {
    
    float test_l[] = { -0.5, 0.0, 0.17, 0.33, 0.50, 0.67, 0.83, 1.0, 1.7};
    float test_r[] = { 0.0, 0.0,  0.0,  0.0,  0.6,  1.0,  1.0, 1.0, 1.};
    float test_g[] = { 0.0, 0.0,  0.0,  1.0,  1.0,  1.0,  0.6, 0.0, 1.};
    float test_b[] = { 0.0, 0.3,  0.8,  1.0,  0.3,  0.0,  0.0, 0.0, 1.};
    
    cpgctab (test_l, test_r, test_g, test_b, 9, contrast, brightness);
    
    break;
  }
  
  } // end switch (name)
}

pgplot::ColourMap::Interface::Interface (ColourMap* instance)
{
  if (instance)
    set_instance (instance);

  add( &ColourMap::get_name,
       &ColourMap::set_name,
       "map", "Name of colour map" );

  add( &ColourMap::get_brightness,
       &ColourMap::set_brightness,
       "bri", "Brightness" );

  add( &ColourMap::get_contrast,
       &ColourMap::set_contrast,
       "con", "Contrast" );

  add( &ColourMap::get_logarithmic,
       &ColourMap::set_logarithmic,
       "log", "Use logarithmic transfer function" );

}

std::ostream& pgplot::operator << (std::ostream& os, ColourMap::Name name)
{
  switch (name) {
  case ColourMap::GreyScale:
    return os << "grey";
  case ColourMap::Inverse:
    return os << "inv";
  case ColourMap::Heat:
    return os << "heat";
  case ColourMap::Cold:
    return os << "cold";
  case ColourMap::Plasma:
    return os << "plasma";
  case ColourMap::Forest:
    return os << "forest";
  case ColourMap::AlienGlow:
    return os << "alien";
  case ColourMap::CubeHelix:
    return os << "cubehelix";
  case ColourMap::Test:
    return os << "test";
  }
  return os;
}

std::istream& pgplot::operator >> (std::istream& is, ColourMap::Name& name)
{
  std::streampos pos = is.tellg();
  std::string unit;
  is >> unit;

  if (unit == "grey")
    name = ColourMap::GreyScale;
  else if (unit == "inv")
    name = ColourMap::Inverse;
  else if (unit == "heat")
    name = ColourMap::Heat;
  else if (unit == "cold")
    name = ColourMap::Cold;
  else if (unit == "plasma")
    name = ColourMap::Plasma;
  else if (unit == "forest")
    name = ColourMap::Forest;
  else if (unit == "alien")
    name = ColourMap::AlienGlow;
  else if (unit == "cubehelix" )
    name = ColourMap::CubeHelix;
  else if (unit == "test")
    name = ColourMap::Test;

  else {

    // replace the text and try to parse a number
    is.seekg (pos);

    int code = -1;
    is >> code;

    if (!is.fail())
      name = (ColourMap::Name) code;

  }

  return is;
}

void ensure_ColourMap_linkage ()
{
}

Pulsar::Option<std::string> pgplot::ColourMap::default_colour_map
(
  "ColourMap::colour_map",
  "heat",
  "Default colour map for various plots",
  "This controls which colour map will be used by default. \n"
  "Possible values: grey, inv, heat, cold, plasma, forest, alien, cubehelix."
);
